1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package com.sun.imageio.plugins.png;
27
28 public class RowFilter {
29
30 private static final int abs(int x) {
31 return (x < 0) ? -x : x;
32 }
33
34
35 protected static int subFilter(byte[] currRow,
36 byte[] subFilteredRow,
37 int bytesPerPixel,
38 int bytesPerRow) {
39 int badness = 0;
40 for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) {
41 int curr = currRow[i] & 0xff;
42 int left = currRow[i - bytesPerPixel] & 0xff;
43 int difference = curr - left;
44 subFilteredRow[i] = (byte)difference;
45
46 badness += abs(difference);
47 }
48
49 return badness;
50 }
51
52
53 protected static int upFilter(byte[] currRow,
54 byte[] prevRow,
55 byte[] upFilteredRow,
56 int bytesPerPixel,
57 int bytesPerRow) {
58 int badness = 0;
59 for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) {
60 int curr = currRow[i] & 0xff;
61 int up = prevRow[i] & 0xff;
62 int difference = curr - up;
63 upFilteredRow[i] = (byte)difference;
64
65 badness += abs(difference);
66 }
67
68 return badness;
69 }
70
71 protected final int paethPredictor(int a, int b, int c) {
72 int p = a + b - c;
73 int pa = abs(p - a);
74 int pb = abs(p - b);
75 int pc = abs(p - c);
76
77 if ((pa <= pb) && (pa <= pc)) {
78 return a;
79 } else if (pb <= pc) {
80 return b;
81 } else {
82 return c;
83 }
84 }
85
86 public int filterRow(int colorType,
87 byte[] currRow,
88 byte[] prevRow,
89 byte[][] scratchRows,
90 int bytesPerRow,
91 int bytesPerPixel) {
92
93
94 if (colorType != PNGImageReader.PNG_COLOR_PALETTE) {
95 System.arraycopy(currRow, bytesPerPixel,
96 scratchRows[0], bytesPerPixel,
97 bytesPerRow);
98 return 0;
99 }
100
101 int[] filterBadness = new int[5];
102 for (int i = 0; i < 5; i++) {
103 filterBadness[i] = Integer.MAX_VALUE;
104 }
105
106 {
107 int badness = 0;
108
109 for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) {
110 int curr = currRow[i] & 0xff;
111 badness += curr;
112 }
113
114 filterBadness[0] = badness;
115 }
116
117 {
118 byte[] subFilteredRow = scratchRows[1];
119 int badness = subFilter(currRow,
120 subFilteredRow,
121 bytesPerPixel,
122 bytesPerRow);
123
124 filterBadness[1] = badness;
125 }
126
127 {
128 byte[] upFilteredRow = scratchRows[2];
129 int badness = upFilter(currRow,
130 prevRow,
131 upFilteredRow,
132 bytesPerPixel,
133 bytesPerRow);
134
135 filterBadness[2] = badness;
136 }
137
138 {
139 byte[] averageFilteredRow = scratchRows[3];
140 int badness = 0;
141
142 for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) {
143 int curr = currRow[i] & 0xff;
144 int left = currRow[i - bytesPerPixel] & 0xff;
145 int up = prevRow[i] & 0xff;
146 int difference = curr - (left + up)/2;;
147 averageFilteredRow[i] = (byte)difference;
148
149 badness += abs(difference);
150 }
151
152 filterBadness[3] = badness;
153 }
154
155 {
156 byte[] paethFilteredRow = scratchRows[4];
157 int badness = 0;
158
159 for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) {
160 int curr = currRow[i] & 0xff;
161 int left = currRow[i - bytesPerPixel] & 0xff;
162 int up = prevRow[i] & 0xff;
163 int upleft = prevRow[i - bytesPerPixel] & 0xff;
164 int predictor = paethPredictor(left, up, upleft);
165 int difference = curr - predictor;
166 paethFilteredRow[i] = (byte)difference;
167
168 badness += abs(difference);
169 }
170
171 filterBadness[4] = badness;
172 }
173
174 int minBadness = filterBadness[0];
175 int filterType = 0;
176
177 for (int i = 1; i < 5; i++) {
178 if (filterBadness[i] < minBadness) {
179 minBadness = filterBadness[i];
180 filterType = i;
181 }
182 }
183
184 if (filterType == 0) {
185 System.arraycopy(currRow, bytesPerPixel,
186 scratchRows[0], bytesPerPixel,
187 bytesPerRow);
188 }
189
190 return filterType;
191 }
192 }